package com.bxl.chooser.oper.impl;

import com.bxl.chooser.bean.AppInfo;
import com.bxl.chooser.bean.ChooseMsg;
import com.bxl.chooser.bean.ChooseResponseMsg;
import com.bxl.chooser.bean.MessageBean;
import com.bxl.chooser.context.ChooserContext;
import com.bxl.chooser.factory.ChooseMsgFactory;
import com.bxl.chooser.factory.MessageBeanFactory;
import com.bxl.chooser.oper.IOperSv;
import com.bxl.chooser.oper.OperDefine;
import com.bxl.netty.rpc.client.common.client.ClientInfo;
import com.bxl.netty.rpc.common.message.PackageMsg;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 选举服务
 *
 * @author baixl
 * @date 2021/3/25
 */
public class AddMessageService implements IOperSv<ChooseResponseMsg> {
    private Logger logger = LoggerFactory.getLogger(AddMessageService.class);

    @Override
    public ChooseResponseMsg oper(PackageMsg<ChooseMsg> msg, ChooserContext context) {
        try {
            AppInfo appInfo = context.getAppInfo();
            synchronized (appInfo) {
                if (appInfo.getState() == AppInfo.AppState.LEADER) {
                    MessageBean messageBean = MessageBeanFactory.ofMessageBeanFactory(String.valueOf(msg.getHeader().getRequestID()), msg.getContent().getMsg(), context.getAppInfo().getTerm(), msg.getContent().getIndex());
                    //leader直接添加内容
                    if (appInfo.addMessage(messageBean)) {
                        //通知follower-写成功-》 发送提交消息，返回客户端成功
                        if (context.getPartners().add(messageBean) > (context.getPartners().getPartnersNum() / 2)) {
                            logger.info("leader 数据写入成功");
                            return ChooseResponseMsg.success;
                        } else {
                            //回滚leader；
                            appInfo.rollback(messageBean.getMessageId());
                            return ChooseResponseMsg.fail;
                        }
                    }
                } else {
                    MessageBean messageBean = MessageBeanFactory.ofMessageBeanFactory(msg.getContent().getMessageId(), msg.getContent().getMsg(), context.getAppInfo().getTerm(), msg.getContent().getIndex());
                    //不是leader，是前端发送的消息，直接返回leader
                    if (msg.getHeader().getFlag() == OperDefine.CLIENTMESSAGE.getOper()) {
                        //当前是无主状态-等待重试
                        if (!context.getHasLeader()) {
                            return ChooseResponseMsg.retry;
                        }
                        ClientInfo leader = context.getLeader();
                        ChooseResponseMsg.change.setLeaderIP(leader.getIp());
                        ChooseResponseMsg.change.setPort(leader.getPort());
                        return ChooseResponseMsg.change;
                    } else {
                        //leader的同步消息，添加数据
                        if (appInfo.addMessage(messageBean)) {
                            logger.info("follower 数据写入成功 消息索引 {}", msg.getContent().getIndex());
                            return ChooseMsgFactory.createChooseResponseMsg(context.getAppInfo().getTerm(), true); //
                        } else {
                            logger.info("follower 数据写入失败 消息索引 {}", msg.getContent().getIndex());
                            //如果是同步消息，返回当前的index
                            if (msg.getHeader().getFlag() == OperDefine.SYNCMESSAGE.getOper()) {
                                return ChooseMsgFactory.createChooseResponseMsg(context.getAppInfo().getTerm(), false, context.getAppInfo().getLogIndex());
                            }
                            return ChooseMsgFactory.createChooseResponseMsg(context.getAppInfo().getTerm(), false);
                        }

                    }

                }
            }

        } catch (Exception e) {
            logger.error("消息写入失败");
        }
        //数据写入失败
        return ChooseMsgFactory.createChooseResponseMsg(context.getAppInfo().getTerm(), false);
    }
}
